import java.util.* ;
import java.util.prefs.BackingStoreException;
import java.io.* ;
import java.nio.* ;
import java.nio.charset.Charset;

import java.io.BufferedReader;
/*import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

file.Paths;
 */

public class Q1part1new{
	
	public static void main(String[] args) {
		

		//added this comment!
		
		//added another comment!!
		
		File toRead = new File ("D:\\Security of Computers\\ex1\\CBC Demo (JDK 1.6)\\CBC Demo JDK 1.6\\Corpus\\tolstoy.txt"); 
		String text = readDoc(toRead); 
		byte[] baInitVector = text.getBytes();
		
		File ivRead = new File ("D:\\Security of Computers\\ex1\\CBC Demo (JDK 1.6)\\CBC Demo JDK 1.6\\IV_10.txt"); 
		String iv = readDoc(ivRead);
		File keyRead = new File ("D:\\Security of Computers\\ex1\\CBC Demo (JDK 1.6)\\CBC Demo JDK 1.6\\myKeyTest.txt"); 
		String key = readDoc(keyRead);
		//	char [] keyArray = key.toCharArray();
		byte[] baKey = key.getBytes();
		byte[] bCipherText = encode(text, iv, baKey); /*this is the text after encription!!! in bytes*/

		String fileName = "D:\\Security of Computers\\ex1\\CBC Demo (JDK 1.6)\\CBC Demo JDK 1.6\\Corpus\\Tolstoy.cipher";
		File writeTo= new File(fileName);
		writeDoc(writeTo, bCipherText);

		
	}
	/* This is tests for the code */
	/*
		char[] simpleText = new char [10];
		char[] simpleDestKey = new char [10];
		char[] simpleSolutaion = new char [10];
		String sText = "abxdcCfa7h";
		String sKey = "bcdefghi";

		simpleText = sText.toCharArray();
		simpleDestKey = sKey.toCharArray();

		//simpleSolutaion = encription(simpleText, simpleDestKey);
		System.out.print(simpleSolutaion);

		/* endof tests*/



	public static String readDoc(File toRead) {
		String text = "";
		int read, N = 1024 * 1024;
		char[] buffer = new char[N];

		try {
			FileReader fr = new FileReader(toRead);
			BufferedReader br = new BufferedReader(fr);

			while(true) {
				read = br.read(buffer, 0, N);
				text += new String(buffer, 0, read);

				if(read < N) {
					break;
				}
			}
		} catch(Exception ex) {
			ex.printStackTrace();
		}

		return text;
	}

	public static void writeDoc(File toWrite, byte[] baToWrite) {
		
	
			BufferedOutputStream bs = null;

			try {

			    FileOutputStream fs = new FileOutputStream(toWrite);
			    bs = new BufferedOutputStream(fs);
			    bs.write(baToWrite);
			    bs.close();
			    bs = null;

			} catch (Exception e) {
			    e.printStackTrace();
			}
	}
	/* gets plainText divide to 10's and do XOR */
	public static byte [] encode(String sText,String sVector, byte [] destKey)
	{
		String sTextCurr;
		byte[] baXorResult;
		byte[] baVectorCipherText; 
		byte[] baCipherText = new byte [sText.length()+10];
		byte[] baInitVector = sVector.getBytes();
		int index =0;

		for (int i=0; i<sText.length();i+=10)
		{
			if (i+10>=sText.length())
			{
				sTextCurr= sText.substring(i);
				for (int j=sTextCurr.length();j<10;j++)
					sTextCurr=sTextCurr+"0";
			}
			else
			{
				sTextCurr= sText.substring(i, i+10);		
			}
			baXorResult= Xor(sTextCurr, baInitVector); /* do xor on the plain text first with iv and then with cipher text*/

			baVectorCipherText= encription(baXorResult, destKey); // encript plainText
			baInitVector = baVectorCipherText; // changes the iv
			
			for (int j=0;j<baVectorCipherText.length;j++)// copy vector cipher values into the full text
			{
				baCipherText[index]=baVectorCipherText[j];
				index++;
			}
		}
		return baCipherText;

	}

	public static byte[] Xor(String sText, byte[] bInitVector)
	{ 

		byte[] baText = sText.getBytes();
		byte[] baXor = new byte [baText.length];

		for( int i = 0; i < 10 ; i++ )
		{
			baXor[i] = (byte)(baText[i] ^ bInitVector[i]);	

		}
		return baXor;

	}
	public static byte[] Xor(byte[] baCurrVector, byte[] bInitVector)
	{ 

		byte[] baXor = new byte [baCurrVector.length];

		for( int i = 0; i < 10 ; i++ )
		{
			baXor[i] = (byte)(baCurrVector[i] ^ bInitVector[i]);	

		}
		return baXor;

	}

	/*gets text and key  returns cipherText */ 
	public static byte [] encription ( byte [] text, byte [] destKey )
	{
		byte [] cipherText = new byte [10];
		int index ;
		for (int i= 0; i<text.length;i++)
		{
			index = compareChar(text[i], destKey);
			if ( index != -1) /* found letter that need to be exchange*/
			{
				cipherText[i] = destKey[index*4 +2];
			}
			else
				cipherText[i]= text[i];

		}
		return cipherText;
	}
	private static int compareChar( byte toCompare, byte[] destKey )/* check if works */
	/* keyLenght is a param for the second part of the work when the key is larger */
	{
		boolean found = false;
		int index = 0;

		if ( destKey.length < 40) /* first part of the exe */
		{

			if( toCompare > 96 && toCompare < 105 )
			{
				while (!found && index<8)
				{
					if ( destKey[index*4] == toCompare)
					{
						found = true;
						return index;
					}
					index++;
				}
				return -1;
			}// not between 'a' to 'h'
		}
		return -1; /* just because the if*/
	}
	
//	public static void decrypFile (byte [] toDycrp, byte [] key, byte [] baInitVector)
//	{
//		byte[] baCurrVector = new byte[10];
//		byte[] baCurrIV=baInitVector.clone();
//		byte[] baXorResult;
//		byte[] baVectorDycripText; 
//		byte[] baDycripText = new byte [toDycrp.length+10];
//		int index =0;
//
//		for (int i=0; i<toDycrp.length;i+=10)
//		{
//			for(int j=0;j<10;j++)
//			{
//				baCurrVector[j]=toDycrp[i+j];
//			}
//			baVectorDycripText= dycription(baCurrVector, key);
//			
//			baXorResult= Xor(baVectorDycripText, baCurrIV); /* do xor on the plain text first with iv and then with cipher text*/
//			
//			for (int j=0;j<baXorResult.length;j++)// copy vector cipher values into the full text
//			{
//				baDycripText[index]=baXorResult[j];
//				index++;
//			}
//			baXorResult =(byte[])baCurrVector.clone();
//			
//			baVectorCipherText= encription(baXorResult, destKey); // encript plainText
//			baInitVector = baVectorCipherText; // changes the iv
//			
//			for (int j=0;j<baVectorCipherText.length;j++)// copy vector cipher values into the full text
//			{
//				baCipherText[index]=baVectorCipherText[j];
//				index++;
//			}
//		}
//		return baCipherText;
//	}

	private static int dyCompareChar( byte toCompare, byte[] destKey )/* check if works */
	/* keyLenght is a param for the second part of the work when the key is larger */
	{
		boolean found = false;
		int index = 0;

		if ( destKey.length < 40) /* first part of the exe */
		{

			if( toCompare > 96 && toCompare < 105 )
			{
				while (!found && index<8)
				{
					if ( destKey[index*4+2] == toCompare)
					{
						found = true;
						return index;
					}
					index++;
				}
				return -1;
			}// not between 'a' to 'h'
		}
		return -1; /* just because the if*/
	}
}



